package system

import (
	"context"
	"encoding/json"
	"fmt"
	"gf-assistant/internal/common/factory"
	"gf-assistant/internal/system/parameter"
	"github.com/gogf/gf/v2/util/gconv"
	"reflect"

	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
)

type MenuDao struct{}

func init() {
	menuDao := MenuDao{}
	factory.Put(reflect.TypeOf(menuDao).String(), &menuDao)
}
func (dao *MenuDao) DB() gdb.DB {
	return g.DB()
}
func (dao *MenuDao) ListMenu(ctx context.Context, req *parameter.ListMenuReq) (menus []*parameter.MenuInfoRes) {
	sql := `
		  select t.MENU_ID as MenuId,t.MENU_NAME as MenuName,t.MENU_CODE as MenuCode,t.PARENT_ID as ParentId,
		         t.ICON as Icon,t.HREF as Href ,t.TARGET AS Target,t.SORT_NUM AS SortNum,
		         t.LEVEL as Level,t.REMARK as  Remark,
		         c.NICK_NAME as CreatedUserName,p.NICK_NAME as UpdatedUserName,
				 DATE_FORMAT(t.CREATE_TIME,'%Y-%m-%d %T') as CreatedTime,
				 DATE_FORMAT(t.UPDATE_TIME,'%Y-%m-%d %T') as UpdatedTime
		  from SYS_MENU t 
		  left join SYS_USER c on t.CREATE_USER=c.USER_ID
		  left join SYS_USER p on t.UPDATE_USER=p.USER_ID
		  where t.ENABLE_STATUS=1
		  order by t.PARENT_ID , t.SORT_NUM desc
		  `
	resultList, err := g.DB().GetAll(ctx, sql)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	//遍历结构体切片
	for _, v := range resultList {
		menu := parameter.MenuInfoRes{}
		err = json.Unmarshal([]byte(v.Json()), &menu)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
		}
		menus = append(menus, &menu)
	}
	return menus
}
func (dao *MenuDao) GetByMenuCode(ctx context.Context, parentId uint, menuCode string) uint {
	parameters := make([]interface{}, 0)
	sql := `
		  select count(t.MENU_ID) cnt
		  from SYS_MENU t 
		  left join SYS_USER c on t.CREATE_USER=c.USER_ID
		  left join SYS_USER p on t.UPDATE_USER=p.USER_ID
		  where t.PARENT_ID=? and t.MENU_CODE=?  
		  `
	parameters = append(parameters, parentId, menuCode)
	one, _ := g.DB().GetOne(ctx, sql, parameters)
	return gconv.Uint(one.Map()["cnt"])
}
func (dao *MenuDao) CreateRootMenu(tx gdb.TX, req *parameter.CreateRootMenuReq) {
	parameters := make([]interface{}, 0)
	sql := `
			insert into SYS_MENU(PARENT_ID,MENU_CODE,MENU_NAME,LEVEL,
			                     ENABLE_STATUS,CREATE_TIME,CREATE_USER,UPDATE_TIME,UPDATE_USER)
			values (0,?,?,1,1,now(),?,now(),?)
			on duplicate key update 
				PARENT_ID=0,
				MENU_NAME=?,
				LEVEL=1,
				ENABLE_STATUS=1,
				UPDATE_TIME=now(),
				UPDATE_USER=?
		  `
	parameters = append(parameters, req.MenuCode, req.MenuName, req.GetOperatorId(), req.GetOperatorId(),
		req.MenuName, req.GetOperatorId())

	_, err := tx.Exec(sql, parameters)
	if err != nil {
		panic("insert menu failed")
	}
}
func (dao *MenuDao) CreateMenu(tx gdb.TX, req *parameter.SaveMenuReq) (res *parameter.SaveMenuRes) {
	parameters := make([]interface{}, 0)
	sql := `
			insert into SYS_MENU(PARENT_ID,MENU_CODE,MENU_NAME,ICON,
			                     HREF,TARGET,SORT_NUM,LEVEL,REMARK,
			                     ENABLE_STATUS,CREATE_TIME,CREATE_USER,UPDATE_TIME,UPDATE_USER)
			values (?,?,?,?,?,?,?,(select (p.LEVEL + 1) from SYS_MENU p where p.MENU_ID=?),?,1,now(),?,now(),?)
			on duplicate key update 
				PARENT_ID=?,
				MENU_NAME=?,
				ICON=?,
				HREF=?,
				TARGET=?,
				SORT_NUM=?,
				LEVEL=(select (p.LEVEL + 1) from SYS_MENU p where p.MENU_ID=?),
				REMARK=?,
				ENABLE_STATUS=1,
				UPDATE_TIME=now(),
				UPDATE_USER=?
		  `
	parameters = append(parameters, req.ParentId, req.MenuCode, req.MenuName, req.Icon, req.Href, req.Target, req.SortNum, req.ParentId, req.Remark, req.GetOperatorId(), req.GetOperatorId(),
		req.ParentId, req.MenuName, req.Icon, req.Href, req.Target, req.SortNum, req.ParentId, req.Remark, req.GetOperatorId())

	result, err := tx.Exec(sql, parameters)
	if err != nil {
		fmt.Printf("insert menu faied, error:[%v]", err.Error())
	}
	insertId, err := result.LastInsertId()
	return &parameter.SaveMenuRes{MenuId: gconv.Uint(insertId)}
}
func (dao *MenuDao) UpdateMenu(tx gdb.TX, req *parameter.SaveMenuReq) {
	parameters := make([]interface{}, 0)
	sql := `
			update SYS_MENU set 
				PARENT_ID=?,
				MENU_CODE=?,
				MENU_NAME=?,
				ICON=?,
				HREF=?,
				TARGET=?,
				SORT_NUM=?,
				REMARK=?,
				ENABLE_STATUS=1,
				UPDATE_TIME=now(),
				UPDATE_USER=?
			where MENU_ID=?
		  `
	parameters = append(parameters, req.ParentId, req.MenuCode, req.MenuName, req.Icon, req.Href, req.Target, req.SortNum, req.Remark, req.GetOperatorId(), req.MenuId)
	_, err := tx.Exec(sql, parameters)
	if err != nil {
		panic("修改菜单失败")
	}
}
func (dao *MenuDao) DeleteMenu(tx gdb.TX, req *parameter.DeleteMenuReq) {
	parameters := make([]interface{}, 0)
	sql := `
			update SYS_MENU set 
				ENABLE_STATUS=0,
				UPDATE_TIME=now(),
				UPDATE_USER=?
			where MENU_ID=?
		  `
	parameters = append(parameters, req.GetOperatorId(), req.MenuId)
	_, err := tx.Exec(sql, parameters)
	if err != nil {
		panic("删除菜单失败")
	}
}
func (dao *MenuDao) GetMenuTree(ctx context.Context, req *parameter.GetPermissionReq) (res []*parameter.PermissionTreeRes) {
	sql := `
		  SELECT  t.MENU_ID as Id, t.PARENT_ID as PId,t.MENU_NAME as Title, t.REMARK as Remark,(CASE WHEN a.ROLE_ID>0 then 1 ELSE 0 end) as AuthState
		  FROM SYS_MENU t
		  LEFT JOIN (
		      SELECT distinct rm.MENU_ID,r.ROLE_ID
		      FROM SYS_ROLE_MENU rm
		      JOIN SYS_ROLE R on r.ROLE_ID=rm.ROLE_ID and r.ENABLE_STATUS=1
		  	  WHERE r.ROLE_ID=?
		  	  	and rm.ENABLE_STATUS=1
		  )a on a.MENU_ID=t.MENU_ID
		  WHERE t.ENABLE_STATUS=1
		  ORDER BY t.PARENT_ID ASC, t.SORT_NUM DESC
		  `
	resultList, err := g.DB().GetAll(ctx, sql, req.RoleId)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	//遍历结构体切片
	for _, v := range resultList {
		menu := parameter.PermissionTreeRes{}
		err = json.Unmarshal([]byte(v.Json()), &menu)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
		}
		res = append(res, &menu)
	}
	return res
}
